﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Text;
using System.Web.Services.Protocols;
using System.Net;
using System.Xml.Xsl;
using System.Xml;

namespace Ashlen.Portal.Services
{
    public class Helper
    {
        #region Properties

        private string proxyUri = string.Empty;

        public string ProxyUri
        {
            get { return proxyUri; }
            set { proxyUri = value; }
        }

        #endregion

        #region Singleton
        private static Helper _instance = null;
        private static object lockObj = new object();
        public static Helper Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (lockObj)
                    {
                        _instance = new Helper();
                    }
                }
                return _instance;
            }
        }
        #endregion

        #region WebDownload
        /// <summary>
        /// Strips the filename from a url
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private string FileName(string url)
        {

            if (url.Equals(string.Empty))
            {
                throw new ArgumentException("Please supply a document url.");
            }
            int loc = url.LastIndexOf("/") + 1;
            int len = url.Length - loc;
            string filename = url.Substring(loc, len);
            return filename;
        }

        /// <summary>
        /// Starts the download of the attached url into the given directory.
        /// </summary>
        public string Download(string url)
        {
            string tempDir = Path.GetTempPath();
            string output = string.Empty;
            if (null == url || url.Equals(string.Empty))
            {
                throw new ArgumentException("Please supply a document url.");
            }

            try
            {
                //IWebProxy proxy = null;
                //if (ProxyUri != null && ProxyUri != string.Empty)
                //{
                //    proxy = new WebProxy(ProxyUri, true);
                //    proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
                //}
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                //if (proxy != null)
                //{
                //    request.Proxy = proxy;
                //}
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                //output = new StreamReader(response.GetResponseStream()).ReadToEnd();
                using (var stream = response.GetResponseStream())
                {
                    byte[] inBuffer = ReadFully(stream, 32768);
                    inBuffer = RemoveByteOrderMark(inBuffer);
                    var enc = new System.Text.UTF8Encoding(true);
                    output = enc.GetString(inBuffer);
                }
            }
            catch
            { }
            return output;
        }

        public byte[] RemoveByteOrderMark(byte[] bytes)
        {
            if (!StartsWithByteOrderMark(bytes))
            {
                return bytes;
            }

            byte[] results = new byte[bytes.Length - 3];
            Array.Copy(bytes, 3, results, 0, bytes.Length - 3);

            return results;
        }

        /// <summary>
        /// Determines if the byte array starts with a byte order mark.
        /// </summary>
        ///
        // <param name="bytes">The bytes.</param>
        /// <returns><c>true</c> if the byte array starts with a byte order mark; otherwise false.</returns>
        public bool StartsWithByteOrderMark(byte[] bytes)
        {
            if (bytes == null)
            {
                return false;
            }

            if (bytes.Length < 3)
            {
                return false;
            }

            return
                bytes[0] == 0xEF &&
                bytes[1] == 0xBB &&
                bytes[2] == 0xBF;
        }

        /// <summary>
        /// Reads data from a stream until the end is reached. The
        /// data is returned as a byte array. An IOException is
        /// thrown if any of the underlying IO calls fail.
        /// </summary>
        /// <param name="stream">The stream to read data from</param>
        /// <param name="initialLength">The initial buffer length</param>
        public byte[] ReadFully(Stream stream, int initialLength)
        {
            /* If we've been passed an unhelpful initial length, just
             use 32K. */
            if (initialLength < 1)
            {
                initialLength = 32768;
            }

            byte[] buffer = new byte[initialLength];
            int read = 0;

            int chunk;
            while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
            {
                read += chunk;

                /* If we've reached the end of our buffer, check to see if there's
                 any more information */
                if (read == buffer.Length)
                {
                    int nextByte = stream.ReadByte();

                    /* End of stream? If so, we're done */
                    if (nextByte == -1)
                    {
                        return buffer;
                    }

                    /* Nope. Resize the buffer, put in the byte we've just
                     read, and continue */
                    byte[] newBuffer = new byte[buffer.Length * 2];
                    Array.Copy(buffer, newBuffer, buffer.Length);
                    newBuffer[read] = (byte)nextByte;
                    buffer = newBuffer;
                    read++;
                }
            }
            /* Buffer is now too big. Shrink it. */
            byte[] ret = new byte[read];
            Array.Copy(buffer, ret, read);
            return ret;
        }
        #endregion

        #region  XSL/XML
        /// <summary>
        /// Takes an XML imput and a XslCompileTransform argument and transforms it
        /// </summary>
        /// <param name="transform"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public String Transform(XslCompiledTransform xsl, String xml)
        {
            StringBuilder sb = new StringBuilder();
            XmlReader xReader = XmlReader.Create(new StringReader(xml));
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.ConformanceLevel = ConformanceLevel.Auto;
            XmlWriter xWriter = XmlWriter.Create(sb, settings);
            xsl.Transform(xReader, xWriter);

            return sb.ToString();
        }

        /// <summary>
        /// Takes a string XSL and XML and transforms it
        /// </summary>
        /// <param name="transform"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public String Transform(String xsl, String xml)
        {
            XslCompiledTransform xslCT = new XslCompiledTransform();
            xslCT.Load(XmlReader.Create(new StringReader(xsl)));
            return Transform(xslCT, xml);
        }

        #endregion

    }
}